﻿using System;
using System.Collections.Generic;
using CoreVirtuoso;
using CoreVirtuoso.Descriptions;
using CoreVirtuoso.Helpers;
using VDS.RDF.Query;
using VDS.RDF.Storage;
using VDS.RDF.Parsing;
using VirtuosoDal.Config;
using VirtuosoDal.Entities;
using VirtuosoDal.Helpers;
using VirtuosoDal.Repositories.RdfRepositories.Interfaces.Events;

namespace VirtuosoDal.Repositories.RdfRepositories.Events
{
   public class GeoLabelsRepository : IGeoLabelsRepository
   {
      public bool GeoLabelExists(string userName, string geoLabel)
      {
         string query = "prefix events:    <http://beaware.at/ontology#> " +
                        "SELECT count(?s) " +
                        "FROM @graph " +
                        "WHERE " +
                        "{" +
                        " ?s events:userName @userName . " +
                        " ?s events:geoLabel @geoLabel . " +
                        "}";

         SparqlParameterizedString sparqlParameterizedString = new SparqlParameterizedString(query);
         sparqlParameterizedString.SetUri("@graph", new Uri(Namespaces.GeoLabelsNamespace));
         sparqlParameterizedString.SetLiteral("@userName", userName);
         sparqlParameterizedString.SetLiteral("@geoLabel", geoLabel);

         using (var virtuosoManager = new VirtuosoManager(ConnectionStringsHelper.GetVirtuosoConnectionString()))
         {
            SparqlResultSet sparqlResultSet = QueryHelper.Query(virtuosoManager, sparqlParameterizedString.ToString(),
                                                                null);

            int count = SparqlResultSetConverter.ToCount(sparqlResultSet);

            if (count == 0)
               return false;

            return true;
         }
      }

      public void UpdateGeoLabelLastUsageDateTime(int geoLabelId, DateTimeOffset newLastUsageDateTime, string userName)
      {
         string query = "sparql prefix events:    <http://beaware.at/ontology#> " +
                        "MODIFY GRAPH @graph " +
                        "DELETE " +
                        "{ " +
                        "  @geoLabel events:lastUsageDateTime ?o " +
                        "} " +
                        "INSERT " +
                        "{ " +
                        "  @geoLabel events:lastUsageDateTime @newLastUsageDateTime " +
                        "} " +
                        "WHERE " +
                        "{ " +
                        "  @geoLabel events:lastUsageDateTime ?o . " +
                        "  @geoLabel events:userName @userName . " +
                        "} ";

         SparqlParameterizedString sparqlParameterizedString = new SparqlParameterizedString(query);
         sparqlParameterizedString.SetUri("@graph", new Uri(Namespaces.GeoLabelsNamespace));
         sparqlParameterizedString.SetUri("@geoLabel",
                                          new Uri(String.Format("{0}{1}", Namespaces.GeoLabelsNamespace, geoLabelId)));
         sparqlParameterizedString.SetLiteral("@newLastUsageDateTime",
                                              newLastUsageDateTime.ToString(XmlSpecsHelper.XmlSchemaDateTimeFormat),
                                              new Uri(XmlSpecsHelper.XmlSchemaDataTypeDateTime));
         sparqlParameterizedString.SetLiteral("@userName", userName);

         using (var virtuosoManager = new VirtuosoManager(ConnectionStringsHelper.GetVirtuosoConnectionString()))
         {
            virtuosoManager.Open(false);
            virtuosoManager.ExecuteNonQuery(sparqlParameterizedString.ToString());
            virtuosoManager.Close(true);
         }
      }

      public IEnumerable<GeoLabelDescription> GetGeoLabels(string userName)
      {
         string query = "prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
                        "prefix owl:       <http://www.w3.org/2002/07/owl#> " +
                        "prefix  rdfs:     <http://www.w3.org/2000/01/rdf-schema#> " +
                        "prefix events:    <http://beaware.at/ontology#> " +
                        "SELECT DISTINCT ?s ?geoLabel ?city ?cityName ?place ?placeName " +
                        "FROM @graph " +
                        "WHERE " +
                        "{ " +
                        " ?s events:userName ?userName . " +
                        " ?s events:geoLabel ?geoLabel . " +
                        " ?s events:city ?city . " +
                        " ?s events:cityName ?cityName . " +
                        " ?s events:place ?place . " +
                        " ?s events:placeName ?placeName . " +
                        " ?s events:lastUsageDateTime ?lastUsageDateTime . " +
                        " FILTER(?userName = @userName)" +
                        "} " +
                        "ORDER BY DESC (?lastUsageDateTime) ";

         SparqlParameterizedString sparqlParameterizedString = new SparqlParameterizedString(query);
         sparqlParameterizedString.SetUri("@graph", new Uri(Namespaces.GeoLabelsNamespace));
         sparqlParameterizedString.SetLiteral("@userName", userName);

         using (var virtuosoManager = new VirtuosoManager(ConnectionStringsHelper.GetVirtuosoConnectionString()))
         {
            SparqlResultSet sparqlResultSet = QueryHelper.Query(virtuosoManager, sparqlParameterizedString.ToString(), null);

            return SparqlResultSetConverter.ToListOfGeoLabelDescriptions(sparqlResultSet);
         }
      }
   }
}